home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / option.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  19KB  |  530 lines

  1. // $Id: option.cpp,v 1.30 2000/01/06 08:24:30 lord Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10.  
  11. #include <ctype.h>
  12. #include "config.h"
  13. #include "option.h"
  14. #include "javasym.h"
  15. #include "error.h"
  16. #include "case.h"
  17.  
  18. #ifdef CYGWIN
  19. #include <sys/cygwin.h>
  20. #endif
  21.  
  22. //
  23. //
  24. //
  25. bool ArgumentExpander::ArgumentExpanded(Tuple<char *> &arguments, char *file_name)
  26. {
  27.     struct stat status;
  28.     FILE *afile = fopen(file_name, "r");
  29.     if (afile && (::SystemStat(file_name, &status) == 0))
  30.     {
  31.         char *buffer = new char[status.st_size + 2];
  32.         int file_size = fread(buffer, 1, status.st_size, afile);
  33.         buffer[file_size] = '\n';
  34.         for (int k = 0; k < file_size; k++)
  35.         {
  36.             //
  37.             // isgraph(c) is true if c is any printing character except space.
  38.             //
  39.             while (buffer[k] == U_SPACE || buffer[k] == U_LINE_FEED || buffer[k] == U_CARRIAGE_RETURN)
  40.                 k++;
  41.  
  42.             int n;
  43.             for (n = k + 1; ! (buffer[n] == U_SPACE || buffer[n] == U_LINE_FEED || buffer[n] == U_CARRIAGE_RETURN); n++)
  44.                 ;
  45.             buffer[n] = U_NULL;
  46.             char *str = new char[n - k + 1];
  47.             strcpy(str, &buffer[k]);
  48.             arguments.Next() = str;
  49.             k = n;
  50.         }
  51.         delete [] buffer;
  52.         fclose(afile);
  53.  
  54.         return true;
  55.     }
  56.  
  57.     return false;
  58. }
  59.  
  60.  
  61. ArgumentExpander::ArgumentExpander(int argc_, char *argv_[])
  62. {
  63.     Tuple<char *> arguments(8192);
  64.     for (int i = 0; i < argc_; i++)
  65.     {
  66.         char *argument = argv_[i];
  67.         if (argument[0] != '@' || (! ArgumentExpanded(arguments, argument + 1)))
  68.         {
  69.             char *str = new char[strlen(argument) + 1];
  70.             strcpy(str, argument);
  71.             arguments.Next() = str;
  72.         }
  73.     }
  74.  
  75.     argc = arguments.Length();
  76.     argv = new char*[argc];
  77.  
  78.     for (int k = 0; k < argc; k++)
  79.         argv[k] = arguments[k];
  80.  
  81.     return;
  82. }
  83.  
  84.  
  85. ArgumentExpander::ArgumentExpander(Tuple<char> &line)
  86. {
  87.     Tuple<char *> arguments(8192);
  88.  
  89.     int end = 0;
  90.     do
  91.     {
  92.         for (; end < line.Length() && line[end] == U_SPACE; end++)
  93.             ;
  94.         if (end < line.Length())
  95.         {
  96.             int start = end;
  97.             for (end++; end < line.Length() && line[end] != U_SPACE; end++)
  98.                 ;
  99.             int length = end - start;
  100.             char *argument = new char[length + 1];
  101.             for (int i = 0, k = start; k < end; i++, k++)
  102.                 argument[i] = line[k];
  103.             argument[length] = U_NULL;
  104.  
  105.             if (argument[0] == '@' && ArgumentExpanded(arguments, argument + 1))
  106.                  delete argument;
  107.             else arguments.Next() = argument;
  108.         }
  109.     } while(end < line.Length());
  110.  
  111.     argc = arguments.Length();
  112.     argv = new char*[argc];
  113.  
  114.     for (int k = 0; k < argc; k++)
  115.         argv[k] = arguments[k];
  116.  
  117.     return;
  118. }
  119.  
  120.  
  121. #ifdef WIN32_FILE_SYSTEM
  122. void Option::SaveCurrentDirectoryOnDisk(char c)
  123. {
  124.     if (! current_directory[c])
  125.     {
  126.         char *disk_directory = NULL,
  127.              disk[3] = { c, U_COLON, U_NULL },
  128.              tmp[1];
  129.  
  130.         if (SetCurrentDirectory(disk))
  131.         {
  132.             DWORD directory_length = GetCurrentDirectory(0, tmp);  // first, get the right size
  133.             disk_directory = new char[directory_length + 1];       // allocate the directory
  134.             DWORD length = GetCurrentDirectory(directory_length, disk_directory);
  135.             if (length <= directory_length)
  136.             {
  137.                 for (char *ptr = disk_directory; *ptr; ptr++)
  138.                     *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  139.             }
  140.         }
  141.  
  142.         if (! disk_directory)
  143.         {
  144.             disk_directory = new char[2];
  145.             strcpy(disk_directory, StringConstant::U8S__DO);
  146.         }
  147.  
  148.         current_directory[Case::ToAsciiLower(c)] = disk_directory;
  149.         current_directory[Case::ToAsciiUpper(c)] = disk_directory;
  150.     }
  151.  
  152.     return;
  153. }
  154. #endif
  155.  
  156.  
  157. Option::Option(ArgumentExpander &arguments) : 
  158.                                               classpath(NULL),
  159.                                               directory(NULL),
  160.                                               dependence_report_name(NULL),
  161.                                               encoding(NULL),
  162. #ifdef HAVE_LIB_ICU_UC
  163.                                               converter(NULL),
  164. #endif
  165.                                               nowrite(false),
  166.                                               deprecation(false),
  167.                                               O(false),
  168.                                               g(false),
  169.                                               verbose(false),
  170.                                               depend(false),
  171.                                               nowarn(false),
  172.                                               classpath_search_order(false),
  173.                                               zero_defect(false),
  174.                                               first_file_index(arguments.argc),
  175.                                               debug_trap_op(0),
  176.                                               debug_dump_lex(false),
  177.                                               debug_dump_ast(false),
  178.                                               debug_unparse_ast(false),
  179.                                               debug_unparse_ast_debug(false),
  180.                                               debug_dump_class(false),
  181.                                               nocleanup(false),
  182.                                               incremental(false),
  183.                                               makefile(false),
  184.                                               dependence_report(false),
  185.                                               bytecode(true),
  186.                                               full_check(false),
  187.                                               unzip(false),
  188.                                               dump_errors(false),
  189.                                               errors(true),
  190.                                               comments(false),
  191.                                               pedantic(false)
  192. {
  193. #ifdef WIN32_FILE_SYSTEM
  194.     for (int j = 0; j < 128; j++)
  195.          current_directory[j] = NULL;
  196.  
  197.     char tmp[1];
  198.     DWORD directory_length = GetCurrentDirectory(0, tmp); // first, get the right size
  199.     char *main_current_directory = new char[directory_length + 1];   // allocate the directory
  200.     DWORD length = GetCurrentDirectory(directory_length, main_current_directory);
  201.     if (length > directory_length)
  202.     {
  203.         delete [] main_current_directory;
  204.         main_current_directory = StringConstant::U8S__DO;
  205.         main_disk = 0;
  206.     }
  207.     else
  208.     {
  209.         for (char *ptr = main_current_directory; *ptr; ptr++)
  210.             *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  211.         main_disk = main_current_directory[0]; // the first character
  212.         current_directory[Case::ToAsciiLower(main_disk)] = main_current_directory;
  213.         current_directory[Case::ToAsciiUpper(main_disk)] = main_current_directory;
  214.     }
  215.     current_directory[0] = main_current_directory;
  216. #endif
  217.  
  218.     Tuple<int> filename_index(2048);
  219.  
  220.     for (int i = 1; i < arguments.argc; i++)
  221.     {
  222.         if (arguments.argv[i][0] == '-')
  223.         {
  224.             if (strcmp(arguments.argv[i],"-classpath") == 0 && ((i + 1) < arguments.argc))
  225.             {
  226.                 classpath = arguments.argv[++i];
  227. #ifdef EBCDIC
  228.                 //
  229.                 //  Maintain CLASSPATH in ASCII and translate back to EBCDIC when building file name
  230.                 //
  231.                 for (int k = 0; k < strlen(classpath); k++)
  232.                     classpath[k] = Code::ToASCII(classpath[k]);
  233. #endif
  234.             }
  235.             else if (strcmp(arguments.argv[i], "-depend") == 0 || strcmp(arguments.argv[i], "-Xdepend") == 0)
  236.                  depend = true;
  237.             else if (strcmp(arguments.argv[i], "-encoding") == 0 && ((i + 1) < arguments.argc))
  238.             {
  239. #ifdef HAVE_LIB_ICU_UC
  240.                 encoding = new char[strlen(arguments.argv[++i]) + 1];
  241.                 strcpy(encoding, arguments.argv[i]);
  242.                 UErrorCode err=U_ZERO_ERROR;
  243.                 converter=ucnv_open(encoding, &err);
  244.                 if(!converter)
  245.                     bad_options.Next() = new OptionError(SemanticError::UNSUPPORTED_ENCODING, encoding); 
  246. #else
  247. // if compiling without ICU support, will only support one encoding (ascii).
  248. #endif
  249.                 continue;
  250.             }
  251.             else if (strcmp(arguments.argv[i],"-verbose") == 0)
  252.                  verbose = true;
  253.             else if (strcmp(arguments.argv[i],"-g") == 0)
  254.                  g = true;
  255.             else if (strcmp(arguments.argv[i], "-O") == 0)
  256.                  O = true;
  257.             else if (strcmp(arguments.argv[i],"-deprecation") == 0)
  258.                  deprecation = true;
  259.             else if (strcmp(arguments.argv[i],"-nowrite") == 0)
  260.                  nowrite = true;
  261.             else if (strcmp(arguments.argv[i],"-nowarn") == 0)
  262.                  nowarn = true;
  263.             else if (strcmp(arguments.argv[i],"-Xstdout") == 0)
  264.                  Coutput.StandardOutput();
  265.             else if (strcmp(arguments.argv[i], "-d") == 0 && ((i + 1) < arguments.argc))
  266.             {
  267.                 ++i;
  268. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  269.                 int length = strlen(arguments.argv[i]);
  270.                 directory = new char[length + 1];
  271.                 strcpy(directory, arguments.argv[i]);
  272. #elif defined(WIN32_FILE_SYSTEM)
  273.                 char disk = (strlen(arguments.argv[i]) >= 2 &&
  274.                             Case::IsAsciiAlpha(arguments.argv[i][0]) &&
  275.                             arguments.argv[i][1] == U_COLON
  276.                                      ? arguments.argv[i][0]
  277.                                      : 0);
  278.                 SaveCurrentDirectoryOnDisk(disk);
  279.                 if (SetCurrentDirectory(arguments.argv[i]))
  280.                 {
  281.                     char tmp[1];
  282.                     DWORD directory_length = GetCurrentDirectory(0, tmp); // first, get the right size
  283.                     directory = new char[directory_length + 1]; // allocate the directory
  284.                     DWORD length = GetCurrentDirectory(directory_length, directory);
  285.                     if (length > directory_length)
  286.                     {
  287.                         delete [] directory;
  288.                         directory = NULL;
  289.                     }
  290.                 }
  291.  
  292.                 ResetCurrentDirectoryOnDisk(disk); // reset the current directory on the disk
  293.                 SetMainCurrentDirectory();       // reset the real current directory...
  294.  
  295.                 if (! directory)
  296.                     bad_options.Next() = new OptionError(SemanticError::INVALID_DIRECTORY, arguments.argv[i]);
  297. #endif
  298. #ifdef EBCDIC
  299.                 //
  300.                 // need to translate directory name to ASCII
  301.                 //
  302.                 for (int k = 0; k < directory_length; k++)
  303.                     directory[k] = Code::ToASCII(directory[k]);
  304. #endif
  305.                 if (directory)
  306.                 {
  307.                     for (char *ptr = directory; *ptr; ptr++)
  308.                         *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  309.                 }
  310.             }
  311.             else bad_options.Next() = new OptionError(SemanticError::INVALID_OPTION, arguments.argv[i]);
  312.         }
  313.         else if (arguments.argv[i][0] == '+')
  314.         {
  315.             if (strcmp(arguments.argv[i], "+A") == 0)
  316.                  debug_dump_ast = true;
  317.             else if (strcmp(arguments.argv[i], "+u") == 0)
  318.                  debug_unparse_ast = true;
  319.             else if (strcmp(arguments.argv[i], "+ud") == 0)
  320.             {
  321.                 debug_unparse_ast = true;
  322.                 debug_unparse_ast_debug = true;
  323.             }
  324. #ifdef EBCDIC
  325.             else if (strcmp(arguments.argv[i], "+ASCII") == 0)
  326.                      ascii = true;
  327. #endif
  328.             else if (strcmp(arguments.argv[i], "+B") == 0)
  329.                  bytecode = false;
  330.             else if (strcmp(arguments.argv[i], "+c") == 0)
  331.                  comments = true;
  332.             else if (strcmp(arguments.argv[i], "+C") == 0)
  333.                  debug_dump_class = true;
  334.             else if (strcmp(arguments.argv[i], "+CSO") == 0)
  335.                  classpath_search_order = true;
  336.             else if (strcmp(arguments.argv[i],"+D") == 0)
  337.             {
  338.                  dump_errors = true;
  339.                  errors = false;
  340.             }
  341.             else if (strcmp(arguments.argv[i],"+E") == 0)
  342.                  errors = false;
  343.             else if (arguments.argv[i][0] == '+' && arguments.argv[i][1] == 'K')
  344.             {
  345.                 char *name = arguments.argv[i] + 2,
  346.                      *image;
  347.                 for (image = name; *image && *image != '='; image++)
  348.                     ;
  349.  
  350.                 if (*image != '=')
  351.                     bad_options.Next() = new OptionError(SemanticError::INVALID_K_OPTION, arguments.argv[i]);
  352.                 else
  353.                 {
  354.                     int key = 0; // assume undefined
  355.                     image++;
  356.  
  357.                     if (strcmp(image, "boolean") == 0)
  358.                          key = TK_boolean;
  359.                     else if (strcmp(image, "byte") == 0)
  360.                          key = TK_byte;
  361.                     else if (strcmp(image, "char") == 0)
  362.                          key = TK_char;
  363.                     else if (strcmp(image, "short") == 0)
  364.                          key = TK_short;
  365.                     else if (strcmp(image, "int") == 0)
  366.                          key = TK_int;
  367.                     else if (strcmp(image, "long") == 0)
  368.                          key = TK_long;
  369.                     else if (strcmp(image, "float") == 0)
  370.                          key = TK_float;
  371.                     else if (strcmp(image, "double") == 0)
  372.                          key = TK_double;
  373.                     else bad_options.Next() = new OptionError(SemanticError::INVALID_K_TARGET, image);
  374.  
  375.                     if (key != 0)
  376.                     {
  377.                         int i = keyword_map.NextIndex();
  378.                         keyword_map[i].key = key;
  379.                         keyword_map[i].length = image - name - 1;
  380.                         keyword_map[i].name = new wchar_t[keyword_map[i].length];
  381.                         for (int k = 0; k < keyword_map[i].length; k++)
  382.                             keyword_map[i].name[k] = name[k];
  383.                     }
  384.                 }
  385.             }
  386.             else if (strcmp(arguments.argv[i],"+F") == 0)
  387.                  full_check = true;
  388.             else if (strcmp(arguments.argv[i],"+M") == 0)
  389.             {
  390.                  makefile = true;
  391.                  full_check = true;
  392.             }
  393.             else if (strncmp(arguments.argv[i], "+DR=", 4) == 0)
  394.             {
  395.                  makefile = true;
  396.                  dependence_report=true;
  397.                  full_check = true;
  398.                  dependence_report_name = &arguments.argv[i][4];
  399.             }
  400.             else if (strcmp(arguments.argv[i], "+O") == 0)
  401.             {
  402.                  debug_trap_op = atoi(arguments.argv[i + 1]);
  403.                  i++;
  404.             }
  405.             else if (strcmp(arguments.argv[i],"+P") == 0)
  406.                  pedantic = true;
  407.             else if (arguments.argv[i][0] == U_PLUS && arguments.argv[i][1] == U_T)
  408.             {
  409.                 int tab_size = 0;
  410.                 char *image = arguments.argv[i] + 2,
  411.                      *p;
  412.                 for (p = image; *p && Code::IsDigit(*p); p++)
  413.                 {
  414.                     int digit = *p - U_0;
  415.                     tab_size = tab_size * 10 + digit;
  416.                 }
  417.  
  418.                 if (*p)
  419.                      bad_options.Next() = new OptionError(SemanticError::INVALID_TAB_VALUE, image);
  420.                 Tab::SetTabSize(tab_size == 0 ? Tab::DEFAULT_TAB_SIZE : tab_size);
  421.             }
  422.             else if (strcmp(arguments.argv[i], "+L") == 0)
  423.                  debug_dump_lex = true;
  424.             else if (strcmp(arguments.argv[i],"+U") == 0)
  425.             {
  426.                  unzip = true;
  427.                  full_check = true;
  428.             }
  429.             else if (strcmp(arguments.argv[i],"++") == 0)
  430.             {
  431.                  incremental = true;
  432.                  full_check = true;
  433.             }
  434.             else if (strcmp(arguments.argv[i], "+Z") == 0)
  435.                  zero_defect = true;
  436.             else bad_options.Next() = new OptionError(SemanticError::INVALID_OPTION, arguments.argv[i]);
  437.         }
  438.         else filename_index.Next() = i;
  439.     }
  440.  
  441.     if (! classpath)
  442.     {
  443.         classpath = getenv("JIKESPATH");
  444.         if (! classpath)
  445.             classpath = getenv("CLASSPATH");
  446.  
  447.         if (classpath)
  448.         {
  449.             /* Create a copy of the classpath string we can modify
  450.                this copy without worry that it will effect the env array */
  451.             char * buf;
  452.             buf = new char[strlen(classpath)];
  453.             strcpy(buf, classpath);
  454.             classpath = buf;
  455.  
  456. #ifdef EBCDIC
  457.             //
  458.             //  Maintain CLASSPATH in ASCII and translate back to EBCDIC when building file name
  459.             //
  460.             for (int k = 0; k < strlen(classpath); k++)
  461.                 classpath[k] = Code::ToASCII(classpath[k]);
  462. #endif
  463.             while (isspace(*classpath))
  464.                 classpath++;
  465.  
  466.             if (*classpath == U_NULL) {
  467.                 delete [] classpath;
  468.                 classpath = NULL;
  469.             }
  470.  
  471. #ifdef CYGWIN
  472.             // Under Cygwin, we convert a windows style path into a unix style path
  473.             // so that we can parse it using the unix path seperator char ':'
  474.             buf = new char[cygwin_win32_to_posix_path_list_buf_size(classpath)];
  475.             cygwin_win32_to_posix_path_list(classpath, buf);
  476.             delete [] classpath;
  477.             classpath = buf;
  478. #endif
  479.         }
  480.  
  481.         if (! classpath)
  482.         {
  483.             classpath = new char[2];
  484.             classpath[0] = '.';
  485.             classpath[1] = U_NULL;
  486.         }
  487.     }
  488.  
  489.     //
  490.     // Initially, first_file_index is set to argc. Since the array filename_index
  491.     // contains the indices of all the input files in arguments in reverse order,
  492.     // we reverse the order here again to get the original list...
  493.     //
  494.     for (int k = filename_index.Length() - 1; k >= 0; k--)
  495.     {
  496.         first_file_index--;
  497.  
  498.         int i = filename_index[k];
  499.         char *temp = arguments.argv[i];
  500.         arguments.argv[i] = arguments.argv[first_file_index];
  501.         arguments.argv[first_file_index] = temp;
  502.     }
  503.  
  504.     //
  505.     // If the traditional batch output form for reporting errors is requested,
  506.     // then wide character expansion is turned on.
  507.     //
  508.     if (errors && (! dump_errors))
  509.         Coutput.SetExpandWchar();
  510.  
  511.     return;
  512. }
  513.  
  514.  
  515. Option::~Option()
  516. {
  517.     for (int i = 0; i < bad_options.Length(); i++)
  518.         delete bad_options[i];
  519.  
  520.     delete [] classpath;
  521.     delete [] directory;
  522.  
  523. #ifdef WIN32_FILE_SYSTEM
  524.     for (char c = 'a'; c <= 'z'; c++)
  525.         delete [] current_directory[c];
  526. #endif
  527.  
  528.     return;
  529. }
  530.